#include "U2Camera.h"

#include "U2SceneManager.h"
#include "U2Viewport.h"





U2EG_NAMESPACE_USING



U2Camera::U2Camera(const U2String& name, U2SceneManager* sm)
: U2Frustum(name)
, mLastViewport(0)
, mAutoAspectRatio(false)
, mVisFacesLastRender(0)
, mVisBatchesLastRender(0)
, mPixelDisplayRatio(0)
, mSceneDetail(PM_SOLID)
, mSceneMgr(sm)
{
}

//-----------------------------------------------------------------------
U2Camera::~U2Camera()
{
}

//-----------------------------------------------------------------------
void U2Camera::setPosition(u2real x, u2real y, u2real z)
{
    mPosition.x = x;
    mPosition.y = y;
    mPosition.z = z;
}

//-----------------------------------------------------------------------
void U2Camera::setPosition(const U2Vector3& vec)
{
    mPosition = vec;
}

//-----------------------------------------------------------------------
const U2Vector3& U2Camera::getPosition(void) const
{
    return mPosition;
}

//-----------------------------------------------------------------------
bool U2Camera::getAutoAspectRatio(void) const
{
    return mAutoAspectRatio;
}

//-----------------------------------------------------------------------
void U2Camera::setAutoAspectRatio(bool autoratio)
{
    mAutoAspectRatio = autoratio;
}

//-----------------------------------------------------------------------
void U2Camera::_notifyRenderedFaces(unsigned int numfaces)
{
    mVisFacesLastRender = numfaces;
}

//-----------------------------------------------------------------------
void U2Camera::_notifyRenderedBatches(unsigned int numbatches)
{
    mVisBatchesLastRender = numbatches;
}

//-----------------------------------------------------------------------
unsigned int U2Camera::_getNumRenderedFaces(void) const
{
    return mVisFacesLastRender;
}

//-----------------------------------------------------------------------
unsigned int U2Camera::_getNumRenderedBatches(void) const
{
    return mVisBatchesLastRender;
}

//-----------------------------------------------------------------------
void U2Camera::setPolygonMode(PolygonMode sd)
{
    mSceneDetail = sd;
}

//-----------------------------------------------------------------------
PolygonMode U2Camera::getPolygonMode(void) const
{
    return mSceneDetail;
}

void U2Camera::_renderScene(U2Viewport *vp)
{
    /**********************#####################
    //update the pixel display ratio
    if (mProjType == PT_PERSPECTIVE)
    {
        mPixelDisplayRatio = (2 * U2Math::Tan(mFOVy * 0.5f)) / vp->getActualHeight();
    }
    else
    */
    {
        mPixelDisplayRatio = (mTop - mBottom) / vp->getActualHeight();
    }

    //notify prerender scene
    for (ListenerList::iterator i = mListeners.begin(); i != mListeners.end(); ++i)
    {
        (*i)->cameraPreRenderScene(this);
    }

    //render scene
    //mSceneMgr->_renderScene(this, vp, includeOverlays)
    mSceneMgr->_renderScene(this, vp);

    //notify postrender scene
    for (ListenerList::iterator i = mListeners.begin(); i != mListeners.end(); ++i)
    {
        (*i)->cameraPostRenderScene(this);
    }
}

//-----------------------------------------------------------------------
const U2Matrix4& U2Camera::getViewMatrix(bool ownFrustumOnly) const
{
    return U2Frustum::getViewMatrix();
    /*
    if (ownFrustumOnly)
    {
        return U2Frustum::getViewMatrix();
    }
    else
    {
        return getViewMatrix();
    }
    */
}
/**********************@@@@@@@@@@@@@@@@@@@@@
//-----------------------------------------------------------------------
void U2Camera::lookAt(const U2Vector3& targetPoint)
{
    updateView();
    this->setDirection(targetPoint - mRealPosition);
}

//-----------------------------------------------------------------------
void U2Camera::lookAt( u2real x, u2real y, u2real z )
{
    U2Vector3 vTemp( x, y, z );
    this->lookAt(vTemp);
}

//-----------------------------------------------------------------------
void U2Camera::setDirection(u2real x, u2real y, u2real z)
{
    setDirection(U2Vector3(x,y,z));
}

//-----------------------------------------------------------------------
void U2Camera::setDirection(const U2Vector3& vec)
{
    // Do nothing if given a zero vector
    // (Replaced assert since this could happen with auto tracking camera and
    //  camera passes through the lookAt point)
    if (vec == U2Vector3::ZERO) return;

    // Remember, camera points down -Z of local axes!
    // Therefore reverse direction of direction vector before determining local Z
    U2Vector3 zAdjustVec = -vec;
    zAdjustVec.normalise();

    U2Quaternion targetWorldOrientation;


    if( mYawFixed )
    {
        U2Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
        xVec.normalise();

        U2Vector3 yVec = zAdjustVec.crossProduct( xVec );
        yVec.normalise();

        targetWorldOrientation.FromAxes( xVec, yVec, zAdjustVec );
    }
    else
    {

        // Get axes from current quaternion
        U2Vector3 axes[3];
        updateView();
        mRealOrientation.ToAxes(axes);
        U2Quaternion rotQuat;
        if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f) 
        {
            // Oops, a 180 degree turn (infinite possible rotation axes)
            // Default to yaw i.e. use current UP
            rotQuat.FromAngleAxis(Radian(U2Math::PI), axes[1]);
        }
        else
        {
            // Derive shortest arc to new direction
            rotQuat = axes[2].getRotationTo(zAdjustVec);
        }
        targetWorldOrientation = rotQuat * mRealOrientation;
    }

    // transform to parent space
    if (mParentNode)
    {
        mOrientation =
            mParentNode->_getDerivedOrientation().Inverse() * targetWorldOrientation;
    }
    else
    {
        mOrientation = targetWorldOrientation;
    }

    // TODO If we have a fixed yaw axis, we mustn't break it by using the
    // shortest arc because this will sometimes cause a relative yaw
    // which will tip the camera

    invalidateView();
}

//-----------------------------------------------------------------------
U2Vector3 U2Camera::getDirection(void) const
{
    // Direction points down -Z by default
    return mOrientation * -U2Vector3::UNIT_Z;
}
*/
